package phaseI;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;


public class NFATable {

	protected Hashtable<String,Hashtable<String,ArrayList<String>>> states;
	protected ArrayList<String> endStates;
	protected int stateCount;
	
	protected ArrayList<String> allStates;
	
	public NFATable()
	{
		this.states = new Hashtable<String,Hashtable<String,ArrayList<String>>>();
		this.endStates = new ArrayList<String>();
		
		this.allStates = new ArrayList<String>();
	}
	
	public void addState(String stateNum)
	{
		states.put(stateNum, new Hashtable<String,ArrayList<String>>());
		if(!allStates.contains(stateNum))
			allStates.add(stateNum);
	}
	
	public void addTransition(String prevState, String nextState, String transition)
	{
		
		if(!allStates.contains(prevState))
			allStates.add(prevState);
		if(!allStates.contains(nextState))
			allStates.add(nextState);
		
		Hashtable<String,ArrayList<String>> prevStateTransList = states.get(prevState);
		if(prevStateTransList == null)
		{
			this.addState(prevState);
			prevStateTransList = states.get(prevState);
		}
		ArrayList<String> nextStates = prevStateTransList.get(transition);
		if(nextStates == null)
		{
			nextStates = new ArrayList<String>();
			prevStateTransList.put(transition, nextStates);
		}
		nextStates.add(nextState);
	}
	
	public void addTransitions(String prevState, ArrayList<String> nextStates, String transition)
	{
		for(String nextState : nextStates)
		{
			this.addTransition(prevState, nextState, transition);
		}
	}
	
	public ArrayList<String> getStatesFromTransition(String prevState, String transition)
	{
		Hashtable<String,ArrayList<String>> prevStateTransList = states.get(prevState);
		if(prevStateTransList==null)
			return null;
		return prevStateTransList.get(transition);
		
	}
	
	public String toString()
	{
		Iterator<Map.Entry<String,Hashtable<String,ArrayList<String>>>> iterStates = states.entrySet().iterator();
		StringBuffer sbuff = new StringBuffer();
		String stateString = "State ";
		String transString = " on transition ";
		String destString = " goes to States: ";
		char nl = '\n';
		while(iterStates.hasNext())
		{
			Map.Entry<String,Hashtable<String,ArrayList<String>>> entry = iterStates.next();
			sbuff.append(stateString);
			sbuff.append(entry.getKey());
			
			Iterator<Map.Entry<String,ArrayList<String>>>iterTrans = entry.getValue().entrySet().iterator();
			while(iterTrans.hasNext())
			{
				Map.Entry<String,ArrayList<String>> entryTrans = iterTrans.next();
				sbuff.append(transString);
				sbuff.append(entryTrans.getKey());
				sbuff.append(destString);
				sbuff.append(entryTrans.getValue().toString());
				sbuff.append(nl);
			}
		}
		return sbuff.toString();
		
	}
	
	public void addEndState(String state)
	{
		endStates.add(state);
	}
	
	public void addEndStates(ArrayList<String> states)
	{
		endStates.addAll(states);
	}
	
	public Hashtable<String,Hashtable<String,ArrayList<String>>> getTable()
	{
		return states;
	}
	
	public ArrayList<String> getStateTransitions()
	{
		ArrayList<String> alist = new ArrayList<String>();
		Iterator<Map.Entry<String,Hashtable<String,ArrayList<String>>>> iterStates = states.entrySet().iterator();
		while(iterStates.hasNext())
		{
			Map.Entry<String,Hashtable<String,ArrayList<String>>> entry = iterStates.next();

			
			Iterator<Map.Entry<String,ArrayList<String>>>iterTrans = entry.getValue().entrySet().iterator();
			while(iterTrans.hasNext())
			{
				String trans = iterTrans.next().getKey();
				if(!alist.contains(trans))
				{
					alist.add(trans);
				}
			}
		}
		return alist;
	}
	
	
	public ArrayList<String> getEndStates()
	{
		return endStates;
	}
	
	public void setEndStates(ArrayList<String> endStates)
	{
		this.endStates = endStates;
	}
	
	public void clearEndStates()
	{
		this.endStates.clear();
	}
	
	public boolean hasEndState(String endState)
	{
		return this.endStates.contains(endState);
	}
	
	public int getStateCount()
	{
		return this.allStates.size();
	}
}
